﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Blizzard.Container
{
    static class RelationDefinitionContainer
    {

        private static Dictionary<Key, RelationDefinition> innerContainer = new Dictionary<Key, RelationDefinition>();

        internal static void ClearContainer()
        {
            innerContainer.Clear();
        }

        public static void Add(RelationDefinition Rd)
        {
            if (HasRd(Rd))
            {
                throw new Exception("this RelationDefinition object already exist in the container");
            }
            else
            {
                Key key = new Key(Rd.TypeRole1.MyType, Rd.TypeRole2.MyType);
                innerContainer.Add(key, Rd);
            }
        }

      
        public static bool HasRd(RelationDefinition Rd)
        {
            return HasRd(Rd.TypeRole1.MyType, Rd.TypeRole2.MyType);
        }

        public static bool HasRd(Type type1, Type type2)
        {


            bool hasrd = false;

            Key key12 = new Key(type1, type2);
            Key key21 = new Key(type2, type1);

            if (innerContainer.ContainsKey(key12))
            {
                hasrd = true;
            }
            else
            {
                if (innerContainer.ContainsKey(key21))
                {
                    hasrd = true;
                }
            }


            return hasrd;

        }

        public static RelationDefinition GetRd(Type type1, Type type2)
        {
            RelationDefinition retRd = null;

            Key key12 = new Key(type1, type2);
            Key key21 = new Key(type2, type1);

            if (innerContainer.ContainsKey(key12))
            {
                retRd = innerContainer[key12];
            }
            else
            {
                if (innerContainer.ContainsKey(key21))
                {
                    retRd = innerContainer[key21];
                }
            }


            return retRd;
        }

        public static List<RelationDefinition> GetAllRelations(Type mainType)
        {
            List<RelationDefinition> retRDs = new List<RelationDefinition>();

            foreach (RelationDefinition rd in innerContainer.Values)
            {
                if (rd.TypeRole1.MyType == mainType || rd.TypeRole2.MyType == mainType)
                {
                    retRDs.Add(rd);
                }

            }

            return retRDs;
        }

        /// <summary>
        /// It gets the parent type when the relationship is OneToMany
        /// if Relation is ManyToMany Or there is no RelationDefinition for
        /// these two types in container, it returns null
        /// </summary>
        /// <param name="rd"></param>
        public static Type GetParentType(Type type1, Type type2)
        {

            RelationDefinition rd = GetRd(type1, type2);

            if (rd.TypeRole1.MyRole == Role.Parent)
            {
                return rd.TypeRole1.MyType;
            }
            else
            {
                return rd.TypeRole2.MyType;
            }


        }

        public static Type GetChildType(Type type1, Type type2)
        {

            RelationDefinition rd = GetRd(type1, type2);

            if (rd.TypeRole1.MyRole == Role.Child)
            {
                return rd.TypeRole1.MyType;
            }
            else
            {
                return rd.TypeRole2.MyType;
            }


        }

        private struct Key
        {
            private Type _type1;
            private Type _type2;

            public Key(Type type1, Type type2)
            {
                _type1 = type1;
                _type2 = type2;
            }

            public Type Type1 { get { return _type1; } }
            public Type Type2 { get { return _type2; } }
        }

    }
}
